﻿using Microsoft.Scripting;
using Microsoft.Scripting.Ast;
using Microsoft.Linq.Expressions;
using DlrBasic.Runtime;
using System;

namespace DlrBasic.Parser.Ast
{
    internal delegate void StatementInvoke(Runtime.DlrBasicState state);

    abstract class Statement : DlrBasicNode
    {
        public Statement(SourceSpan span)
            : base(span)
        {
        }

        internal protected LambdaExpression GenerateExecutableStatement(DlrBasicGenerator generator, string id)
        {
            LambdaBuilder builder = Utils.Lambda(typeof(void), "Statement_" + id);
            ParameterExpression stateParameter = builder.Parameter(typeof(DlrBasicState), "state");
            generator.CurrentStateParameter = stateParameter;
            
            builder.Body = Generate(generator, new StateMemberGenerator(stateParameter), builder);

            generator.CurrentStateParameter = null;
            return builder.MakeLambda(typeof(StatementInvoke));
        }
        
        internal protected virtual Expression Generate(DlrBasicGenerator generator, StateMemberGenerator stateParameter, LambdaBuilder builder)
        {
            return Expression.Assign(stateParameter.GetCurrentStatementVariable(),
                Expression.Constant(generator.GetNextStatementNumber(this)));
        }

        public virtual void Visit(StatementsVisitor vistor)
        {
            vistor.Statement(this);
        }
    }

}
